﻿using System;
using System.Collections.Generic;
using System.Text;
using AI.Fuzzy.Library;

namespace LRSS
{
    public class FuzzyLogicSystemFactory
    {
        const int MAX_Hollowness = 5000;
        const int MAX_Tl_Pch = 100;

        public MamdaniFuzzySystem CreateSystem()
        {
            MamdaniFuzzySystem _srFuzzyLogicSystem = new MamdaniFuzzySystem();
            //
            // Create input variables for the system
            //
            #region Hollowness 0.0 -- Unknown MAX ;may be some bug!
            FuzzyVariable Hollowness = new FuzzyVariable("Hollowness", 0.0, MAX_Hollowness);
            Hollowness.Terms.Add(new FuzzyTerm("Trapezia", new TrapezoidMembershipFunction(TrapeziaFuzzy_Hollowness.X1, TrapeziaFuzzy_Hollowness.X2, TrapeziaFuzzy_Hollowness.X3, TrapeziaFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("ConcentricHelix", new TrapezoidMembershipFunction(ConcentricHelixFuzzy_Hollowness.X1, ConcentricHelixFuzzy_Hollowness.X2, ConcentricHelixFuzzy_Hollowness.X3, ConcentricHelixFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("Delete", new TrapezoidMembershipFunction(DeleteFuzzy_Hollowness.X1, DeleteFuzzy_Hollowness.X2, DeleteFuzzy_Hollowness.X3, DeleteFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("Arc", new TrapezoidMembershipFunction(ArcFuzzy_Hollowness.X1, ArcFuzzy_Hollowness.X2, ArcFuzzy_Hollowness.X3, ArcFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("Curve", new TrapezoidMembershipFunction(CurveFuzzy_Hollowness.X1, CurveFuzzy_Hollowness.X2, CurveFuzzy_Hollowness.X3, CurveFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("FoldLine", new TrapezoidMembershipFunction(FoldLineFuzzy_Hollowness.X1, FoldLineFuzzy_Hollowness.X2, FoldLineFuzzy_Hollowness.X3, FoldLineFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("Spiral", new TrapezoidMembershipFunction(SpiralFuzzy_Hollowness.X1, SpiralFuzzy_Hollowness.X2, SpiralFuzzy_Hollowness.X3, SpiralFuzzy_Hollowness.X4)));
            Hollowness.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Hollowness.X1, OtherFuzzy_Hollowness.X2, OtherFuzzy_Hollowness.X3, OtherFuzzy_Hollowness.X4)));
            _srFuzzyLogicSystem.Input.Add(Hollowness);
            #endregion

            #region Tl_Pch 0.0 --Unknown
            FuzzyVariable Tl_Pch = new FuzzyVariable("Tl_Pch", 0.0, MAX_Hollowness);
            Tl_Pch.Terms.Add(new FuzzyTerm("Delete", new TrapezoidMembershipFunction(DeleteFuzzy_Tl_Pch.X1, DeleteFuzzy_Tl_Pch.X2, DeleteFuzzy_Tl_Pch.X3, DeleteFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("Pentacle", new TrapezoidMembershipFunction(PentacleFuzzy_Tl_Pch.X1, PentacleFuzzy_Tl_Pch.X2, PentacleFuzzy_Tl_Pch.X3, PentacleFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("Arc", new TrapezoidMembershipFunction(ArcFuzzy_Tl_Pch.X1, ArcFuzzy_Tl_Pch.X2, ArcFuzzy_Tl_Pch.X3, ArcFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("Curve", new TrapezoidMembershipFunction(CurveFuzzy_Tl_Pch.X1, CurveFuzzy_Tl_Pch.X2, CurveFuzzy_Tl_Pch.X3, CurveFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("Trapezia", new TrapezoidMembershipFunction(TrapeziaFuzzy_Tl_Pch.X1, TrapeziaFuzzy_Tl_Pch.X2, TrapeziaFuzzy_Tl_Pch.X3, TrapeziaFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("FoldLine", new TrapezoidMembershipFunction(FoldLineFuzzy_Tl_Pch.X1, FoldLineFuzzy_Tl_Pch.X2, FoldLineFuzzy_Tl_Pch.X3, FoldLineFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("Unclose", new TrapezoidMembershipFunction(UncloseFuzzy_Tl_Pch.X1, UncloseFuzzy_Tl_Pch.X2, UncloseFuzzy_Tl_Pch.X3, UncloseFuzzy_Tl_Pch.X4)));
            Tl_Pch.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Tl_Pch.X1, OtherFuzzy_Tl_Pch.X2, OtherFuzzy_Tl_Pch.X3, OtherFuzzy_Tl_Pch.X4)));
            _srFuzzyLogicSystem.Input.Add(Tl_Pch);
            #endregion

            //Todo Diamond 
            //Todo Pentacle

            #region Her_Wer 0.0 -- 1.0
            FuzzyVariable Her_Wer = new FuzzyVariable("Her_Wer", 0.0, 1.0);
            Her_Wer.Terms.Add(new FuzzyTerm("Line", new TrapezoidMembershipFunction(LineFuzzy_Her_Wer.X1, LineFuzzy_Her_Wer.X2, LineFuzzy_Her_Wer.X3, LineFuzzy_Her_Wer.X4)));
            Her_Wer.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Her_Wer.X1, OtherFuzzy_Her_Wer.X2, OtherFuzzy_Her_Wer.X3, OtherFuzzy_Her_Wer.X4)));
            _srFuzzyLogicSystem.Input.Add(Her_Wer);
            #endregion

            #region Pch2_Ach4PI 1.0 --5.0
            FuzzyVariable Pch2_Ach4PI = new FuzzyVariable("Pch2_Ach4PI", 0.0, 300);
            Pch2_Ach4PI.Terms.Add(new FuzzyTerm("Circles", new TrapezoidMembershipFunction(CirclesFuzzy_Pch2_Ach4PI.X1, CirclesFuzzy_Pch2_Ach4PI.X2, CirclesFuzzy_Pch2_Ach4PI.X3, CirclesFuzzy_Pch2_Ach4PI.X4)));
            Pch2_Ach4PI.Terms.Add(new FuzzyTerm("Trapezia", new TrapezoidMembershipFunction(TrapeziaFuzzy_Pch2_Ach4PI.X1, TrapeziaFuzzy_Pch2_Ach4PI.X2, TrapeziaFuzzy_Pch2_Ach4PI.X3, TrapeziaFuzzy_Pch2_Ach4PI.X4)));
            Pch2_Ach4PI.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Pch2_Ach4PI.X1, OtherFuzzy_Pch2_Ach4PI.X2, OtherFuzzy_Pch2_Ach4PI.X3, OtherFuzzy_Pch2_Ach4PI.X4)));
            Pch2_Ach4PI.Terms.Add(new FuzzyTerm("ConcentricHelix", new TrapezoidMembershipFunction(ConcentricHelixFuzzy_Pch2_Ach4PI.X1, ConcentricHelixFuzzy_Pch2_Ach4PI.X2, ConcentricHelixFuzzy_Pch2_Ach4PI.X3, ConcentricHelixFuzzy_Pch2_Ach4PI.X4)));
            _srFuzzyLogicSystem.Input.Add(Pch2_Ach4PI);
            #endregion


            #region Alt_Ach 0.0 -- 1.0
            FuzzyVariable Alt_Ach = new FuzzyVariable("Alt_Ach", 0.0, 1.0);
            Alt_Ach.Terms.Add(new FuzzyTerm("Triangle", new TrapezoidMembershipFunction(TriangleFuzzy_Alt_Ach.X1, TriangleFuzzy_Alt_Ach.X2, TriangleFuzzy_Alt_Ach.X3, TriangleFuzzy_Alt_Ach.X4)));
            Alt_Ach.Terms.Add(new FuzzyTerm("Arc", new TrapezoidMembershipFunction(ArcFuzzy_Alt_Ach.X1, ArcFuzzy_Alt_Ach.X2, ArcFuzzy_Alt_Ach.X3, ArcFuzzy_Alt_Ach.X4)));
            Alt_Ach.Terms.Add(new FuzzyTerm("Curve", new TrapezoidMembershipFunction(CurveFuzzy_Alt_Ach.X1, CurveFuzzy_Alt_Ach.X2, CurveFuzzy_Alt_Ach.X3, CurveFuzzy_Alt_Ach.X4)));
            _srFuzzyLogicSystem.Input.Add(Alt_Ach);
            #endregion

            #region Alt_Alq 0.0 -- 1.0
            FuzzyVariable Alt_Alq = new FuzzyVariable("Alt_Alq", 0.0, 1.0);
            Alt_Alq.Terms.Add(new FuzzyTerm("Triangle", new TrapezoidMembershipFunction(TriangleFuzzy_Alt_Alq.X1, TriangleFuzzy_Alt_Alq.X2, TriangleFuzzy_Alt_Alq.X3, TriangleFuzzy_Alt_Alq.X4)));
            Alt_Alq.Terms.Add(new FuzzyTerm("Diamond", new TrapezoidMembershipFunction(DiamondFuzzy_Alt_Alq.X1, DiamondFuzzy_Alt_Alq.X2, DiamondFuzzy_Alt_Alq.X3, DiamondFuzzy_Alt_Alq.X4)));
            Alt_Alq.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Alt_Alq.X1, OtherFuzzy_Alt_Alq.X2, OtherFuzzy_Alt_Alq.X3, OtherFuzzy_Alt_Alq.X4)));
            _srFuzzyLogicSystem.Input.Add(Alt_Alq);
            #endregion Alt_Alq

            #region Alt_Aer 0.0 -- 0.51
            FuzzyVariable Alt_Aer = new FuzzyVariable("Alt_Aer", 0.0, 5.1);
            Alt_Aer.Terms.Add(new FuzzyTerm("Curve", new TrapezoidMembershipFunction(CurveFuzzy_Alt_Aer.X1, CurveFuzzy_Alt_Aer.X2, CurveFuzzy_Alt_Aer.X3, CurveFuzzy_Alt_Aer.X4)));
            Alt_Aer.Terms.Add(new FuzzyTerm("Arc", new TrapezoidMembershipFunction(ArcFuzzy_Alt_Aer.X1, ArcFuzzy_Alt_Aer.X2, ArcFuzzy_Alt_Aer.X3, ArcFuzzy_Alt_Aer.X4)));
            _srFuzzyLogicSystem.Input.Add(Alt_Aer);
            #endregion

            #region Ach_Aer 0.0 -- 1.0
            FuzzyVariable Ach_Aer = new FuzzyVariable("Ach_Aer", 0.0, 1.0);
            Ach_Aer.Terms.Add(new FuzzyTerm("Rectangle", new TrapezoidMembershipFunction(RectangleFuzzy_Ach_Aer.X1, RectangleFuzzy_Ach_Aer.X2, RectangleFuzzy_Ach_Aer.X3, RectangleFuzzy_Ach_Aer.X4)));
            Ach_Aer.Terms.Add(new FuzzyTerm("Diamond", new TrapezoidMembershipFunction(DiamondFuzzy_Ach_Aer.X1, DiamondFuzzy_Ach_Aer.X2, DiamondFuzzy_Ach_Aer.X3, DiamondFuzzy_Ach_Aer.X4)));
            Ach_Aer.Terms.Add(new FuzzyTerm("Triangle", new TrapezoidMembershipFunction(TriangleFuzzy_Ach_Aer.X1, TriangleFuzzy_Ach_Aer.X2, TriangleFuzzy_Ach_Aer.X3, TriangleFuzzy_Ach_Aer.X4)));
            Ach_Aer.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Ach_Aer.X1, OtherFuzzy_Ach_Aer.X2, OtherFuzzy_Ach_Aer.X3, OtherFuzzy_Ach_Aer.X4)));
            _srFuzzyLogicSystem.Input.Add(Ach_Aer);

            #endregion Ach_Aer

            #region Alq_Aer 0.0 -- 1.0
            FuzzyVariable Alq_Aer = new FuzzyVariable("Alq_Aer", 0.0, 1.0);
            Alq_Aer.Terms.Add(new FuzzyTerm("Rectangle", new TrapezoidMembershipFunction(RectangleFuzzy_Alq_Aer.X1, RectangleFuzzy_Alq_Aer.X2, RectangleFuzzy_Alq_Aer.X3, RectangleFuzzy_Alq_Aer.X4)));
            Alq_Aer.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Alq_Aer.X1, OtherFuzzy_Alq_Aer.X2, OtherFuzzy_Alq_Aer.X3, OtherFuzzy_Alq_Aer.X4)));
            _srFuzzyLogicSystem.Input.Add(Alq_Aer);

            #endregion

            #region Alq_Ach 0.0 -- 1.0
            FuzzyVariable Alq_Ach = new FuzzyVariable("Alq_Ach", 0.0, 1.0);
            Alq_Ach.Terms.Add(new FuzzyTerm("Ellipse", new TrapezoidMembershipFunction(EllipseFuzzy_Alq_Ach.X1, EllipseFuzzy_Alq_Ach.X2, EllipseFuzzy_Alq_Ach.X3, EllipseFuzzy_Alq_Ach.X4)));
            Alq_Ach.Terms.Add(new FuzzyTerm("Other", new TrapezoidMembershipFunction(OtherFuzzy_Alq_Ach.X1, OtherFuzzy_Alq_Ach.X2, OtherFuzzy_Alq_Ach.X3, OtherFuzzy_Alq_Ach.X4)));
            _srFuzzyLogicSystem.Input.Add(Alq_Ach);

            #endregion

            #region Plq_Pch 0.0 -- 1.0
            FuzzyVariable Plq_Pch = new FuzzyVariable("Plq_Pch", 0.0, 1.0);
            Plq_Pch.Terms.Add(new FuzzyTerm("FoldLine", new TrapezoidMembershipFunction(FoldLineFuzzy_Plq_Pch.X1, FoldLineFuzzy_Plq_Pch.X2, FoldLineFuzzy_Plq_Pch.X3, FoldLineFuzzy_Plq_Pch.X4)));
            Plq_Pch.Terms.Add(new FuzzyTerm("Spiral", new TrapezoidMembershipFunction(SpiralFuzzy_Plq_Pch.X1, SpiralFuzzy_Plq_Pch.X2, SpiralFuzzy_Plq_Pch.X3, SpiralFuzzy_Plq_Pch.X4)));
            _srFuzzyLogicSystem.Input.Add(Plq_Pch);
            #endregion
            //
            // Create output variables for the system
            //
            FuzzyVariable Sharp = new FuzzyVariable("Sharp", 0.0, 140.0);
            Sharp.Terms.Add(new FuzzyTerm("Line", new TriangularMembershipFunction(0.0, 5.0, 10.0)));
            Sharp.Terms.Add(new FuzzyTerm("Triangle", new TriangularMembershipFunction(10.0, 15.0, 20.0)));
            Sharp.Terms.Add(new FuzzyTerm("Rectangle", new TriangularMembershipFunction(20.0, 25.0, 30.0)));
            Sharp.Terms.Add(new FuzzyTerm("Circles", new TriangularMembershipFunction(30.0, 35.0, 40.0)));
            Sharp.Terms.Add(new FuzzyTerm("Ellipse", new TriangularMembershipFunction(40.0, 45.0, 50.0)));
            Sharp.Terms.Add(new FuzzyTerm("Diamond", new TriangularMembershipFunction(50.0, 55.0, 60.0)));
            Sharp.Terms.Add(new FuzzyTerm("Trapezia", new TriangularMembershipFunction(60.0, 65.0, 70.0)));
            Sharp.Terms.Add(new FuzzyTerm("FoldLine", new TriangularMembershipFunction(70.0, 75.0, 80.0)));
            Sharp.Terms.Add(new FuzzyTerm("Spiral", new TriangularMembershipFunction(80.0, 85.0, 90.0)));
            Sharp.Terms.Add(new FuzzyTerm("ConcentricHelix", new TriangularMembershipFunction(90.0, 95.0, 100.0)));
            Sharp.Terms.Add(new FuzzyTerm("Curve", new TriangularMembershipFunction(100.0, 105.0, 110.0)));
            Sharp.Terms.Add(new FuzzyTerm("Arc", new TriangularMembershipFunction(110.0, 115.0, 120.0)));
            Sharp.Terms.Add(new FuzzyTerm("Delete", new TriangularMembershipFunction(120.0, 125.0, 130.0)));
            Sharp.Terms.Add(new FuzzyTerm("Pentacle", new TriangularMembershipFunction(130.0, 135.0, 140.0)));
            Sharp.Terms.Add(new FuzzyTerm("Unknown", new TriangularMembershipFunction(10.0, 75.0, 140.0)));
            _srFuzzyLogicSystem.Output.Add(Sharp);
            //
            // Create  fuzzy rules
            //
            try
            {
                //string lastRule = "if  (Her_Wer is not Line) " +
                //                  "and (Pch2_Ach4PI is not Circles) " +
                //                  "and ((Alt_Alq is not Triangle) and (Alt_Ach is not Triangle)) " +
                //                  "and ((Ach_Aer is Other) or (Alq_Aer is Other)) " +
                //                  "and (Tl_Pch is Other) " +
                //                  "then  Sharp is Unknown";

                MamdaniFuzzyRule rule_line = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is Line ) then Sharp is Line");
                MamdaniFuzzyRule rule_Circles = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Pch2_Ach4PI is Circles) and (Hollowness is Other) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Circles");
                MamdaniFuzzyRule rule_ConcentricHelix = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Pch2_Ach4PI is ConcentricHelix) and (Hollowness is ConcentricHelix) and (Tl_Pch is not Delete) then Sharp is ConcentricHelix");
                MamdaniFuzzyRule rule_Triangle = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Tl_Pch is not Unclose) and ((Alt_Ach is Triangle) or (Alt_Alq is Triangle)) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Triangle");
                MamdaniFuzzyRule rule_Rectangle = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and ((Ach_Aer is Rectangle) and (Alq_Aer is Rectangle)) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Rectangle");
                MamdaniFuzzyRule rule_Delete = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Tl_Pch is Delete) and (Pch2_Ach4PI is not Circles) then Sharp is Delete");
                MamdaniFuzzyRule rule_Pentacle = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Tl_Pch is Pentacle) then Sharp is Pentacle");
                MamdaniFuzzyRule rule_Ellipse = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Alq_Ach is Ellipse) and (Pch2_Ach4PI is not Circles) and (Tl_Pch is not Unclose) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Ellipse");
                MamdaniFuzzyRule rule_Arc = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Tl_Pch is Arc) and (Hollowness is Arc) and (Hollowness is not Curve) and  (Alt_Aer is Arc) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Arc");

                MamdaniFuzzyRule rule_Trapezia = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Tl_Pch is Trapezia) and (Pch2_Ach4PI is Trapezia) and (Alt_Ach is not Triangle) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Trapezia");
                MamdaniFuzzyRule rule_Diamond = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Alt_Alq is Diamond) and (Ach_Aer is not Rectangle) and (Hollowness is not Curve) and (Hollowness is not FoldLine) and (Hollowness is not Spiral) then Sharp is Diamond");
                MamdaniFuzzyRule rule_Curve = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Tl_Pch is Curve) and (Hollowness is Curve) and (Alt_Ach is Curve) then Sharp is Curve");
                MamdaniFuzzyRule rule_FoldLine = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Hollowness is FoldLine) and (Plq_Pch is FoldLine) and (Tl_Pch is FoldLine) then Sharp is FoldLine ");
                MamdaniFuzzyRule rule_Spiral = _srFuzzyLogicSystem.ParseRule("if (Her_Wer is not Line) and (Hollowness is Spiral) and (Plq_Pch is Spiral) and (Pch2_Ach4PI is not Circles) and (Pch2_Ach4PI is not ConcentricHelix) then Sharp is Spiral");
               // MamdaniFuzzyRule rule_Last = _srFuzzyLogicSystem.ParseRule(lastRule);



                _srFuzzyLogicSystem.Rules.Add(rule_line);
                _srFuzzyLogicSystem.Rules.Add(rule_Circles);
                _srFuzzyLogicSystem.Rules.Add(rule_ConcentricHelix);
                _srFuzzyLogicSystem.Rules.Add(rule_Triangle);
                _srFuzzyLogicSystem.Rules.Add(rule_Rectangle);
                _srFuzzyLogicSystem.Rules.Add(rule_Delete);
                _srFuzzyLogicSystem.Rules.Add(rule_Pentacle);
                _srFuzzyLogicSystem.Rules.Add(rule_Ellipse);
                _srFuzzyLogicSystem.Rules.Add(rule_Arc);
                _srFuzzyLogicSystem.Rules.Add(rule_Trapezia);
                _srFuzzyLogicSystem.Rules.Add(rule_Diamond);
                _srFuzzyLogicSystem.Rules.Add(rule_Curve);
                _srFuzzyLogicSystem.Rules.Add(rule_FoldLine);
                _srFuzzyLogicSystem.Rules.Add(rule_Spiral);
               // _srFuzzyLogicSystem.Rules.Add(rule_Last);
            }
            catch (Exception ex)
            {
               // System.Windows.Forms.MessageBox.Show(string.Format("Parsing exception: {0}", ex.Message));
                return null;
            }
            return _srFuzzyLogicSystem;
        }
    }
}
